package com.sdp.right.flow.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.sdp.core.bizc.threadLocal.ContextManager;
import com.sdp.core.bizc.utils.ApplicationContextUtils;
import com.sdp.core.bizc.utils.CoreConstantsEnum;
import com.sdp.core.bizc.vo.BusinessContext;
import com.sdp.right.db.sys_emp.service.ISysEmpService;
import com.sdp.right.db.sys_flow_current_task.service.ISysFlowCurrentTaskService;
import com.sdp.right.db.sys_flow_instance.service.ISysFlowInstanceService;
import com.sdp.right.db.sys_flow_node_attribute_version.service.ISysFlowNodeAttributeVersionService;
import com.sdp.right.db.sys_flow_task_his.service.ISysFlowTaskHisService;
import com.sdp.right.db.sys_role_person.service.ISysRolePersonService;
import com.sdp.right.entity.SysEmp;
import com.sdp.right.entity.SysFlowCurrentTask;
import com.sdp.right.entity.SysFlowInstance;
import com.sdp.right.entity.SysFlowNodeAttributeVersion;
import com.sdp.right.entity.SysFlowNodeJumpVersion;
import com.sdp.right.entity.SysFlowTaskHis;
import com.sdp.right.entity.SysRolePerson;
import com.sdp.right.flow.FlowConditionParse;
import com.sdp.right.flow.dto.FlowParam;
import com.sdp.right.flow.service.ISysFlowApproveService;
import com.sdp.right.utils.RightConstants;

import cn.hutool.core.bean.BeanUtil;

@Service
@DS(value="right")
public class SysFlowApproveServiceImpl implements ISysFlowApproveService{
	
	@Autowired
	private ISysFlowCurrentTaskService iSysFlowCurrentTaskService;
	
	@Autowired
	private ISysFlowTaskHisService iSysFlowTaskHisService;
	
	@Autowired
	private ISysFlowInstanceService iSysFlowInstanceService;
	
	@Autowired
	private ISysFlowNodeAttributeVersionService iSysFlowNodeAttributeVersionService;
	
	@Autowired
	private ISysRolePersonService iSysRolePersonService;
	
	@Autowired
	private ISysEmpService iSysEmpService;

	
	/**
	 * 检查审批数据是否合法
	 */
	@Override
	public BusinessContext flowCheck(FlowParam flowParam) {
		BusinessContext businessContext = new BusinessContext();
		
		//当前环节信息
		SysFlowNodeAttributeVersion nodeAttribute = flowParam.getCurrentNodeAttribute();
		
		//如果有任务ID，判断当前任务是否存在，当前任务是否已经审批过，当前任务的环节是否与前台传入的一致
		if(!StringUtils.isEmpty(flowParam.getTaskId())) {
			SysFlowCurrentTask task = iSysFlowCurrentTaskService.getById(flowParam.getTaskId());
			if(task==null) {
				businessContext.setSuccess(false);
				businessContext.setMessage("审批任务不存在");
				return businessContext;
			}
			if(!RightConstants.流程审批状态_审批中.getCode().equals(task.getApprovalState())) {
				businessContext.setSuccess(false);
				businessContext.setMessage("此任务已审批过");
				return businessContext;
			}
			
			if(!nodeAttribute.getNodeNo().equals(task.getCurrentNodeId())) {
				businessContext.setSuccess(false);
				businessContext.setMessage("审批的任务与当前任务不符");
				return businessContext;
			}
			
		}
		return businessContext;
	}

	/**
	 * 流程审批
	 */
	@Override
	public BusinessContext flowApprove(FlowParam flowParam) {
		BusinessContext businessContext = new BusinessContext();
		
		//当前环节信息
		SysFlowNodeAttributeVersion nodeAttribute = flowParam.getCurrentNodeAttribute();
		
		//确定下个环节
		SysFlowNodeJumpVersion nexNode = ApplicationContextUtils.getBean(SysFlowApproveServiceImpl.class).confirmNexNode(flowParam);
		if(nexNode==null) {
			businessContext.setSuccess(false);
			businessContext.setMessage("无法确定下个环节");
			return businessContext;
		}
		flowParam.setNexNode(nexNode);
		
		if(!StringUtils.isEmpty(flowParam.getTaskId())) {
			flowParam.setNexNode(null);
			SysFlowCurrentTask task = iSysFlowCurrentTaskService.getById(flowParam.getTaskId());
			if(RightConstants.否.getCode().equals(flowParam.getPass())) {
				task.setApprovalState(RightConstants.流程审批状态_驳回.getCode());
			}else {
				task.setApprovalState(RightConstants.流程审批状态_通过.getCode());
			}
			task.setApprovalOpinion(flowParam.getApprovalOpinion());
			task.setApprovalTime(LocalDateTime.now());
			task.setProfilePicture(flowParam.getSysEmp().getProfilePicture());
			
			//更新历史任务
			iSysFlowTaskHisService.updateById(BeanUtil.copyProperties(task, SysFlowTaskHis.class));
			
			if(RightConstants.流程节点通过模式_1人办理即可通过.getCode().equals(nodeAttribute.getNodePassMode())) {
				ApplicationContextUtils.getBean(SysFlowApproveServiceImpl.class).onePersonHandle(flowParam, task,nexNode);
			}else {
				//如果是多人办理，如果一个人不通过，则就返回,不管其他人是否已经审批过，或者是否同意
				if(RightConstants.否.getCode().equals(flowParam.getPass())) {
					ApplicationContextUtils.getBean(SysFlowApproveServiceImpl.class).onePersonHandle(flowParam, task,nexNode);
				}else {
					//这里指派人员暂时做这样的处理，如果一个环节，多个人审批通过才向下走，那如果多个人提交到下个环节，指定的人员不一样，怎么办？
					//这里就以最后办理人提交的人为准
					ApplicationContextUtils.getBean(SysFlowApproveServiceImpl.class).morePersonHandle(flowParam, task, nexNode);
				}
			}
			
			if(RightConstants.流程节点结束环节名称.getCode().equals(nexNode.getEndNodeLabel())) {
				flowParam.setNexNode(null);
				flowParam.setIsEnd(RightConstants.是.getCode());
				flowParam.setEndNodeAttribute(iSysFlowNodeAttributeVersionService.queryFlowNodeAttributeVersion(task.getTemplateVersion(), task.getTemplateNo(), nexNode.getEndNodeNo()));
				SysFlowInstance instance = iSysFlowInstanceService.getById(task.getInstanceId());
				instance.setEndTime(LocalDateTime.now());
				iSysFlowInstanceService.updateById(instance);
			}
		}
		
		return businessContext;
	}
	
	/**
	 * 流程提交
	 */
	@Override
	public BusinessContext flowSubmit(FlowParam flowParam) {
		BusinessContext businessContext = new BusinessContext();
		if(flowParam.getNexNode()==null) {
			return businessContext;
		}
		
		
		//当前环节信息
		SysFlowNodeAttributeVersion nodeAttribute = flowParam.getCurrentNodeAttribute();
		
		//下个环节是否为返回
		if(RightConstants.是.getCode().equals(flowParam.getNexNode().getIsReturn())) {
			if(StringUtils.isEmpty(flowParam.getInstanceId())) {
				businessContext.setSuccess(false);
				businessContext.setMessage("没有找到审批任务，无法返回");
				return businessContext;
			}
			ApplicationContextUtils.getBean(SysFlowApproveServiceImpl.class).returnNodePerson(flowParam, nodeAttribute);
		}else if(RightConstants.流程节点人员指派模式_指定人员.getCode().equals(nodeAttribute.getNodeAssigneeMode())
				|| RightConstants.流程节点人员指派模式_动态人员.getCode().equals(nodeAttribute.getNodeAssigneeMode())) {
			if(StringUtils.isEmpty(nodeAttribute.getNodeAssigneeEmpNo())) {
				businessContext.setSuccess(false);
				businessContext.setMessage("指定的审批人员不能为空");
				return businessContext;
			}
		}else if(RightConstants.流程节点人员指派模式_指定角色.getCode().equals(nodeAttribute.getNodeAssigneeMode()) 
				|| RightConstants.流程节点人员指派模式_动态角色.getCode().equals(nodeAttribute.getNodeAssigneeMode())) {
			if(StringUtils.isEmpty(nodeAttribute.getNodeAssigneeRole())) {
				businessContext.setSuccess(false);
				businessContext.setMessage("指定的角色不能为空");
				return businessContext;
			}
			//根据角色得到审批人
			List<SysRolePerson> rolePersons = iSysRolePersonService.querySysRolePersonByRoleNo(nodeAttribute.getNodeAssigneeRole());
			if(rolePersons==null || rolePersons.size()==0) {
				businessContext.setSuccess(false);
				businessContext.setMessage("指定的角色不存在人员");
				return businessContext;
			}
			ApplicationContextUtils.getBean(SysFlowApproveServiceImpl.class).rolePerson(flowParam, nodeAttribute, rolePersons);
		}
		
		if(StringUtils.isEmpty(nodeAttribute.getNodeAssigneeEmpNo())) {
			businessContext.setSuccess(false);
			businessContext.setMessage("审批人员不能为空");
			return businessContext;
		}
		
		List<SysFlowCurrentTask> currentTaskList = new ArrayList<>();
		SysFlowCurrentTask currentTask = null;
		
		String [] assigneeEmpNos = nodeAttribute.getNodeAssigneeEmpNo().split(",");
		String [] assigneeEmpNames = nodeAttribute.getNodeAssigneeEmpName().split(",");
		LocalDateTime now = LocalDateTime.now();
		for(int i=0;i<assigneeEmpNos.length;i++) {
			currentTask = new SysFlowCurrentTask();
			currentTask.setTemplateName(flowParam.getTemplateName());
			currentTask.setInstanceId(flowParam.getInstanceId());
			currentTask.setApprovalEmpNo(assigneeEmpNos[i]);
			currentTask.setApprovalEmpName(assigneeEmpNames[i]);
			currentTask.setSystemNo(nodeAttribute.getSystemNo());
			currentTask.setCurrentNodeId(flowParam.getNexNode().getEndNodeNo());
			currentTask.setCurrentNodeLabel(flowParam.getNexNode().getEndNodeLabel());
			currentTask.setSubmitEmpNo(ContextManager.getContextData(CoreConstantsEnum.token中工号的属性名.getCode()));
			currentTask.setSubmitEmpName(ContextManager.getContextData(CoreConstantsEnum.token中姓名的属性名.getCode()));
			currentTask.setStartTime(now);
			currentTask.setApprovalState(RightConstants.流程审批状态_审批中.getCode());
			currentTask.setCreateTime(now);
			currentTask.setTemplateNo(flowParam.getTemplateNo());
			currentTask.setTemplateVersion(nodeAttribute.getTemplateVersion());
			currentTask.setPageId(nodeAttribute.getPageId());
			currentTask.setTemplateForm(nodeAttribute.getTemplateForm());
			currentTaskList.add(currentTask);
		}
		iSysFlowCurrentTaskService.saveBatch(currentTaskList);
		iSysFlowTaskHisService.saveBatch(JSONArray.parseArray(JSON.toJSONString(currentTaskList), SysFlowTaskHis.class));
		
		return businessContext;
	
	}
	
	/**
	 * 确定下个环节
	 * @param flowParam
	 * @return
	 */
	public SysFlowNodeJumpVersion confirmNexNode(FlowParam flowParam) {
		//根据跳转信息要确定下个环节信息
		List<SysFlowNodeJumpVersion> nodeJumpList = flowParam.getCurrentNodeJump();
		SysFlowNodeJumpVersion nextLink = null;
		for(SysFlowNodeJumpVersion jump : nodeJumpList) {
			if(StringUtils.isEmpty(jump.getJumpCondition())) {
				nextLink = jump;
			}else {
				if(FlowConditionParse.parse(jump.getJumpCondition(), flowParam.getVariable())) {
					nextLink = jump;
					break;
				}
			}
		}
		return nextLink;
	}
	
	/**
	 * 一人办理级通过的模式
	 * @param flowParam
	 * @param task
	 */
	public void onePersonHandle(FlowParam flowParam,SysFlowCurrentTask task,SysFlowNodeJumpVersion nexNode) {
		//删除当前任务中，所有关于此实例，此节点的任务
		iSysFlowCurrentTaskService.removeApprovalCurrentTask(task.getInstanceId(), task.getCurrentNodeId());
		//删除历史任务中，此实例，此节点，未审批的任务
		iSysFlowTaskHisService.removeApprovalTaskHis(task.getInstanceId(), task.getCurrentNodeId());
		flowParam.setNexNode(nexNode);
	}
	
	/**
	 * 多人办理
	 * @param flowParam
	 * @param task
	 * @param nexNode
	 */
	public void morePersonHandle(FlowParam flowParam,SysFlowCurrentTask task,SysFlowNodeJumpVersion nexNode) {
		//删除当前办理人的任务，因为当前办理人已经在办理了
		iSysFlowCurrentTaskService.removeById(task.getKeyId());
		//查看当前实例，此节点的当前任务是否还有
		int count = iSysFlowCurrentTaskService.queryApprovalCurrentTaskCount(task.getInstanceId(),task.getCurrentNodeId());
		if(count==0) {
			//表示当前环节可以结束，可以向下个环节流转
			flowParam.setNexNode(nexNode);
		}
	}
	
	/**
	 * 如果是返回，则找到此节点的提交人，将任务返回
	 * @param flowParam
	 * @param nodeAttribute
	 */
	public void returnNodePerson(FlowParam flowParam,SysFlowNodeAttributeVersion nodeAttribute) {
		//如果是返回，则查找返回的环节是誰提交的，然后将任务指派给誰,因为有可能上个环节是多人办理，所以这里应该查询的是个集合
		List<SysFlowTaskHis> hisList = iSysFlowTaskHisService.queryLastApprovalFlowTaskHis(flowParam.getInstanceId(), flowParam.getNexNode().getEndNodeNo());
		StringBuffer empNoSbf = new StringBuffer("");
		StringBuffer empNameSbf = new StringBuffer("");
		LocalDateTime startTime = null;
		for(SysFlowTaskHis his : hisList) {
			if(startTime==null) {
				startTime = his.getStartTime();
				
			}else if(!startTime.isEqual(his.getStartTime())) {
				break;
			}
			
			empNoSbf.append(his.getApprovalEmpNo());
			empNoSbf.append(",");
			
			empNameSbf.append(his.getApprovalEmpName());
			empNameSbf.append(",");
			
		}
		empNoSbf.deleteCharAt(empNoSbf.length() - 1); 
		empNameSbf.deleteCharAt(empNameSbf.length() - 1); 
		nodeAttribute.setNodeAssigneeEmpNo(empNoSbf.toString());
		nodeAttribute.setNodeAssigneeEmpName(empNameSbf.toString());
	}

	/**
	 * 根据角色找到人
	 * @param flowParam
	 * @param nodeAttribute
	 * @param rolePersons
	 */
	public void rolePerson(FlowParam flowParam,SysFlowNodeAttributeVersion nodeAttribute,List<SysRolePerson> rolePersons) {
	
		List<String> accountNos = new ArrayList<>();
		for(SysRolePerson p : rolePersons) {
			accountNos.add(p.getAccountNo());
		}
		List<SysEmp> empList = iSysEmpService.querySysEmpByAccountNos(accountNos);
		StringBuffer empNoSbf = new StringBuffer("");
		StringBuffer empNameSbf = new StringBuffer("");
		for(SysEmp emp : empList) {
			empNoSbf.append(emp.getEmpNo());
			empNoSbf.append(",");
			
			empNameSbf.append(emp.getEmpName());
			empNameSbf.append(",");
		}
		empNoSbf.deleteCharAt(empNoSbf.length() - 1); 
		empNameSbf.deleteCharAt(empNameSbf.length() - 1); 
		nodeAttribute.setNodeAssigneeEmpNo(empNoSbf.toString());
		nodeAttribute.setNodeAssigneeEmpName(empNameSbf.toString());
	}
	

}
